{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们已经知道，可以直接作用于`for`循环的数据类型有以下几种：\n",
    "\n",
    "- 一类是集合数据类型，如`list`、`tuple`、`dict`、`set`、`str`等；\n",
    "- 一类是`generator`，包括生成器和带`yield`的`generator function`。\n",
    "\n",
    "这些可以直接作用于`for`循环的对象统称为**可迭代对象：`Iterable`** 。可以使用isinstance()判断一个对象是否是Iterable对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "from collections import Iterable\n",
    "\n",
    "print(isinstance([], Iterable))\n",
    "print(isinstance({}, Iterable))\n",
    "print(isinstance(\"abc\", Iterable))\n",
    "print(isinstance((x for x in range(10)), Iterable))\n",
    "print(isinstance(100, Iterable))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "而生成器不但可以作用于`for`循环，还可以被`next()`函数不断调用并返回下一个值，直到最后抛出`StopIteration`错误表示无法继续返回下一个值了。可以被`next()`函数调用并不断返回下一个值的对象称为 **迭代器：Iterator** 。\n",
    "\n",
    "可以使用`isinstance()`判断一个对象是否是`Iterator`对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "False\n",
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "from collections import Iterator\n",
    "\n",
    "print(isinstance((x for x in range(10)), Iterator))\n",
    "print(isinstance([], Iterator))\n",
    "print(isinstance({}, Iterator))\n",
    "print(isinstance(\"abc\", Iterator))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生成器都是`Iterator`对象，但`list`、`dict`、`str`虽然是`Iterable`，却不是`Iterator`。把`list`、`dict`、`str`等`Iterable`变成`Iterator`可以使用`iter()`函数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(isinstance(iter([]), Iterator))\n",
    "print(isinstance(iter(\"abc\"), Iterator))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "你可能会问，为什么`list`、`dict`、`str`等数据类型不是`Iterator`？\n",
    "\n",
    "这是因为`Python`的`Iterator`对象表示的是一个数据流，`Iterator`对象可以被`next()`函数调用并不断返回下一个数据，直到没有数据时抛出`StopIteration`错误。可以把这个数据流看做是一个有序序列，但我们却不能提前知道序列的长度，只能不断通过`next()`函数实现按需计算下一个数据，所以`Iterator`的计算是惰性的，只有在需要返回下一个数据时它才会计算。\n",
    "\n",
    "`Iterator`甚至可以表示一个无限大的数据流，例如全体自然数。而使用`list`是永远不可能存储全体自然数的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**小结**\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "凡是可作用于`for`循环的对象都是`Iterable`类型；\n",
    "\n",
    "凡是可作用于`next()`函数的对象都是`Iterator`类型，它们表示一个惰性计算的序列；\n",
    "\n",
    "集合数据类型如`list`、`dict`、`str`等是`Iterable`但不是`Iterator`，不过可以通过`iter()`函数获得一个`Iterator`对象。\n",
    "\n",
    "Python的`for`循环本质上就是通过不断调用`next()`函数实现的，例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "for x in [1, 2, 3, 4]:\n",
    "    pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "等价于"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "it = iter([1, 2, 3, 4])\n",
    "while True:\n",
    "    try:\n",
    "        x = next(it)\n",
    "    except StopIteration:\n",
    "        break;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
